package org.example;

import instrument.DBUtil;
import instrument.JdbcUtil;
import instrument.LogUtil;
import instrument.MD5Util;
import product.*;

import java.util.*;
import java.text.SimpleDateFormat;

public class ManagerService {
    private final List<Movie> movies = new ArrayList<>();
    private final List<Show> shows = new ArrayList<>();
    private final List<SaleRecord> saleRecords = new ArrayList<>();
    private User currentManager;
    private final Scanner sc = new Scanner(System.in);
    private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    private int showIdCounter = 1000;
    private final AdminService admin;  // 新增AdminService引用

    public ManagerService(AdminService admin) {
        this.admin = admin;  // 初始化AdminService
        DBUtil.initDB();
        movies.addAll(JdbcUtil.loadMovies());
        shows.addAll(JdbcUtil.loadShows(movies));
        saleRecords.addAll(JdbcUtil.loadSaleRecords(shows));
        if (shows.isEmpty()) initTestData();
        showIdCounter = shows.stream().mapToInt(Show::getId).max().orElse(1000);
    }

    public void setCurrentManager(User u) {
        currentManager = u;
    }

    public boolean isLoggedIn() {
        return currentManager != null;
    }

    public void saveData() {
        JdbcUtil.saveMovies(movies);
        JdbcUtil.saveShows(shows);
        JdbcUtil.saveSaleRecords(saleRecords);
    }

    private void initTestData() {
        movies.add(new Movie("流浪地球", "郭帆", "吴京,屈楚萧", "太阳毁灭", 125, 9.0, true));
        movies.add(new Movie("满江红", "张艺谋", "沈腾,易烊千玺", "悬疑故事", 159, 8.5, true));
    }

    public void showManagerMenu() {
        while (isLoggedIn()) {
            System.out.println("\n=== 经理菜单 ===");
            System.out.println("1.密码管理 2.影片管理 3.排片管理 4.销售数据 5.退出");
            switch (sc.nextLine().trim()) {
                case "1" -> pwdManage();
                case "2" -> movieManage();
                case "3" -> showManage();
                case "4" -> saleReport();
                case "5" -> {
                    logout();
                    return;
                }
                default -> System.out.println("无效选择");
            }
        }
    }

    private void pwdManage() {
        System.out.println("1.修改自身密码 2.重置前台密码");
        switch (sc.nextLine().trim()) {
            case "1" -> {
                System.out.print("新密码: ");
                String np = sc.nextLine();
                currentManager.setPassword(MD5Util.encrypt(np));
                currentManager.setNeedChangePassword(false);
                JdbcUtil.saveUsers(admin.getUsers());
                LogUtil.log(currentManager.getUsername(), "经理修改自身密码");
            }
            case "2" -> {
                System.out.print("前台用户名: ");
                String n = sc.nextLine();
                User u = admin.getUsers().stream()
                        .filter(x -> x.getUsername().equals(n) && x.getUserType().equals("前台"))
                        .findFirst().orElse(null);
                if (u == null) {
                    System.out.println("前台不存在");
                    return;
                }
                u.setPassword(MD5Util.encrypt("123456"));
                u.setNeedChangePassword(true);
                JdbcUtil.saveUsers(admin.getUsers());
                LogUtil.log(currentManager.getUsername(), "经理重置前台" + n + "密码");
            }
            default -> System.out.println("无效选择");
        }
    }

    private void movieManage() {
        while (true) {
            System.out.println("\n1.列出所有影片 2.添加影片 3.修改影片 4.删除影片 5.查询影片 6.返回");
            switch (sc.nextLine().trim()) {
                case "1" -> movies.forEach(Movie::display);
                case "2" -> addMovie();
                case "3" -> modifyMovie();
                case "4" -> deleteMovie();
                case "5" -> queryMovie();
                case "6" -> {
                    return;
                }
            }
        }
    }

    private void addMovie() {
        System.out.print("片名: ");
        String name = sc.nextLine();
        System.out.print("导演: ");
        String director = sc.nextLine();
        System.out.print("主演: ");
        String actors = sc.nextLine();
        System.out.print("简介: ");
        String intro = sc.nextLine();
        System.out.print("时长(分钟): ");
        int dur = Integer.parseInt(sc.nextLine());
        System.out.print("评分(0-10): ");
        double score = Double.parseDouble(sc.nextLine());
        movies.add(new Movie(name, director, actors, intro, dur, score, true));
        JdbcUtil.saveMovies(movies);
        LogUtil.log(currentManager.getUsername(), "添加影片" + name);
    }

    private void modifyMovie() {
        System.out.print("输入要修改的影片名: ");
        String name = sc.nextLine();
        Movie m = movies.stream().filter(x -> x.getName().equals(name)).findFirst().orElse(null);
        if (m == null) {
            System.out.println("影片不存在");
            return;
        }
        System.out.print("新导演: ");
        String director = sc.nextLine();
        System.out.print("新主演: ");
        String actors = sc.nextLine();
        System.out.print("新简介: ");
        String intro = sc.nextLine();
        System.out.print("新时长(分钟): ");
        int dur = Integer.parseInt(sc.nextLine());
        System.out.print("新评分(0-10): ");
        double score = Double.parseDouble(sc.nextLine());
        m.setDirector(director);
        m.setActors(actors);
        m.setIntro(intro);
        m.setDuration(dur);
        m.setScore(score);
        JdbcUtil.saveMovies(movies);
        LogUtil.log(currentManager.getUsername(), "修改影片" + name);
    }

    private void deleteMovie() {
        System.out.print("输入要删除的影片名: ");
        String name = sc.nextLine();
        Movie m = movies.stream().filter(x -> x.getName().equals(name)).findFirst().orElse(null);
        if (m == null) {
            System.out.println("影片不存在");
            return;
        }
        if (shows.stream().anyMatch(s -> s.getMovie().getName().equals(name))) {
            System.out.println("影片正在上映，无法删除");
            return;
        }
        System.out.print("确认删除(y/n)? ");
        if (!sc.nextLine().trim().equalsIgnoreCase("y")) return;
        movies.remove(m);
        JdbcUtil.saveMovies(movies);
        LogUtil.log(currentManager.getUsername(), "删除影片" + name);
    }

    private void queryMovie() {
        System.out.print("输入查询条件(片名/导演/主演): ");
        String keyword = sc.nextLine();
        movies.stream()
                .filter(m -> m.getName().contains(keyword) || m.getDirector().contains(keyword) || m.getActors().contains(keyword))
                .forEach(Movie::display);
    }

    private void showManage() {
        while (true) {
            System.out.println("\n1.增加场次 2.修改场次 3.删除场次 4.列出所有场次 5.自动排片 6.返回");
            switch (sc.nextLine().trim()) {
                case "1" -> addShow();
                case "2" -> modifyShow();
                case "3" -> deleteShow();
                case "4" -> listShows();
                case "5" -> autoSchedule();
                case "6" -> {
                    return;
                }
            }
        }
    }

    private void addShow() {
        if (movies.isEmpty()) {
            System.out.println("请先添加影片");
            return;
        }
        for (int i = 0; i < movies.size(); i++) {
            System.out.println((i + 1) + ". " + movies.get(i).getName());
        }
        System.out.print("选择影片序号: ");
        int idx = Integer.parseInt(sc.nextLine()) - 1;
        System.out.print("放映厅: ");
        String hall = sc.nextLine();
        System.out.print("时间(yyyy-MM-dd HH:mm): ");
        try {
            Date time = sdf.parse(sc.nextLine());
            System.out.print("票价: ");
            double price = Double.parseDouble(sc.nextLine());
            System.out.print("行数: ");
            int row = Integer.parseInt(sc.nextLine());
            System.out.print("列数: ");
            int col = Integer.parseInt(sc.nextLine());
            shows.add(new Show(++showIdCounter, movies.get(idx), hall, time, price, row, col));
            JdbcUtil.saveShows(shows);
            LogUtil.log(currentManager.getUsername(), "增加场次" + movies.get(idx).getName() + " " + time);
        } catch (Exception e) {
            System.out.println("格式错误");
        }
    }

    private void modifyShow() {
        System.out.print("输入要修改的场次ID: ");
        int id = Integer.parseInt(sc.nextLine());
        Show s = shows.stream().filter(x -> x.getId() == id).findFirst().orElse(null);
        if (s == null) {
            System.out.println("场次不存在");
            return;
        }
        if (saleRecords.stream().anyMatch(r -> r.getShow().getId() == id)) {
            System.out.println("该场次已售出票，无法修改");
            return;
        }
        System.out.print("新放映厅: ");
        String hall = sc.nextLine();
        System.out.print("新时间(yyyy-MM-dd HH:mm): ");
        try {
            Date time = sdf.parse(sc.nextLine());
            System.out.print("新票价: ");
            double price = Double.parseDouble(sc.nextLine());
            // 假设Show类有以下setter方法（需在Show类中实现）
            s.setHall(hall);
            s.setTime(time);
            s.setPrice(price);
            JdbcUtil.saveShows(shows);
            LogUtil.log(currentManager.getUsername(), "修改场次" + id + " " + time);
        } catch (Exception e) {
            System.out.println("格式错误");
        }
    }

    private void deleteShow() {
        System.out.print("输入要删除的场次ID: ");
        int id = Integer.parseInt(sc.nextLine());
        Show s = shows.stream().filter(x -> x.getId() == id).findFirst().orElse(null);
        if (s == null) {
            System.out.println("场次不存在");
            return;
        }
        if (saleRecords.stream().anyMatch(r -> r.getShow().getId() == id)) {
            System.out.println("该场次已售出票，无法删除");
            return;
        }
        System.out.print("确认删除(y/n)? ");
        if (!sc.nextLine().trim().equalsIgnoreCase("y")) return;
        shows.remove(s);
        JdbcUtil.saveShows(shows);
        LogUtil.log(currentManager.getUsername(), "删除场次" + id);
    }

    private void listShows() {
        System.out.println("\n=== 所有场次 ===");
        shows.forEach(s -> System.out.printf("ID:%d 影片:%s 厅:%s 时间:%s 票价:%.2f%n",
                s.getId(), s.getMovie().getName(), s.getHall(),
                sdf.format(s.getTime()), s.getPrice()));
    }

    private void autoSchedule() {
        List<Movie> showingMovies = movies.stream().filter(Movie::isShowing).toList();
        if (showingMovies.isEmpty()) {
            System.out.println("没有正在上映的影片");
            return;
        }
        Calendar cal = Calendar.getInstance();
        for (Movie m : showingMovies) {
            for (int i = 0; i < 3; i++) {
                cal.add(Calendar.DAY_OF_YEAR, i);
                cal.set(Calendar.HOUR_OF_DAY, 18);
                cal.set(Calendar.MINUTE, 0);
                Date time = cal.getTime();
                shows.add(new Show(++showIdCounter, m, "厅1", time, 50.0, 10, 10));
                cal.add(Calendar.DAY_OF_YEAR, -i); // 重置日期
            }
        }
        JdbcUtil.saveShows(shows);
        LogUtil.log(currentManager.getUsername(), "自动排片");
    }

    private void saleReport() {
        while (true) {
            System.out.println("\n1.查看当日销售数据 2.查看当周销售数据 3.查看当月销售数据 4.返回");
            switch (sc.nextLine().trim()) {
                case "1" -> reportToday();
                case "2" -> reportWeek();
                case "3" -> reportMonth();
                case "4" -> {
                    return;
                }
            }
        }
    }

    private void reportToday() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        Date start = cal.getTime();

        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        Date end = cal.getTime();

        List<SaleRecord> todayRecords = saleRecords.stream()
                .filter(r -> r.getSaleTime().after(start) && r.getSaleTime().before(end))
                .toList();
        System.out.println("\n=== 当日销售数据 ===");
        todayRecords.forEach(r -> System.out.printf("票号:%s 影片:%s 座位:%d,%d 价格:%.2f 售出时间:%s%n",
                r.getTicketId(), r.getShow().getMovie().getName(), r.getSeat().getRow(), r.getSeat().getCol(),
                r.getPrice(), sdf.format(r.getSaleTime())));
    }

    private void reportWeek() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        Date start = cal.getTime();

        cal.add(Calendar.DAY_OF_WEEK, 6);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        Date end = cal.getTime();

        List<SaleRecord> weekRecords = saleRecords.stream()
                .filter(r -> r.getSaleTime().after(start) && r.getSaleTime().before(end))
                .toList();
        System.out.println("\n=== 当周销售数据 ===");
        System.out.printf("总销售票数:%d 总销售金额:%.2f 总退票数:%d 退票金额:%.2f%n",
                weekRecords.size(), weekRecords.stream().mapToDouble(SaleRecord::getPrice).sum(),
                (int) weekRecords.stream().filter(SaleRecord::isRefunded).count(),
                weekRecords.stream().filter(SaleRecord::isRefunded).mapToDouble(SaleRecord::getRefundAmount).sum());
    }

    private void reportMonth() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        Date start = cal.getTime();

        cal.add(Calendar.MONTH, 1);
        cal.set(Calendar.DAY_OF_MONTH, 0);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        Date end = cal.getTime();

        List<SaleRecord> monthRecords = saleRecords.stream()
                .filter(r -> r.getSaleTime().after(start) && r.getSaleTime().before(end))
                .toList();
        System.out.println("\n=== 当月销售数据 ===");
        System.out.printf("总销售票数:%d 总销售金额:%.2f 总退票数:%d 退票金额:%.2f%n",
                monthRecords.size(), monthRecords.stream().mapToDouble(SaleRecord::getPrice).sum(),
                (int) monthRecords.stream().filter(SaleRecord::isRefunded).count(),
                monthRecords.stream().filter(SaleRecord::isRefunded).mapToDouble(SaleRecord::getRefundAmount).sum());
    }

    public void logout() {
        currentManager = null;
        System.out.println("已退出");
    }

    // Getters for other services
    public List<Movie> getMovies() {
        return movies;
    }

    public List<Show> getShows() {
        return shows;
    }

    public List<SaleRecord> getSaleRecords() {
        return saleRecords;
    }

    public Show findShowById(int id) {
        return shows.stream().filter(s -> s.getId() == id).findFirst().orElse(null);
    }

    public void addSaleRecord(SaleRecord sr) {
        saleRecords.add(sr);
    }
}